#include "LecteurPhraseSimple.h"

#include <stdlib.h>
#include <iostream>
using namespace std;

////////////////////////////////////////////////////////////////////////////////

LecteurPhraseSimple::LecteurPhraseSimple(string nomFich) :
ls(nomFich) {
}

////////////////////////////////////////////////////////////////////////////////

void LecteurPhraseSimple::analyse() {
    programme();
    cout << "Syntaxe correcte." << endl;
}

////////////////////////////////////////////////////////////////////////////////

void LecteurPhraseSimple::programme() {
    // <programme> ::= debut <seqInst> fin FIN_FICHIER

    sauterSymCour("debut");
    seqInst();
    sauterSymCour("fin");
    testerSymCour("<FINDEFICHIER>");
}

////////////////////////////////////////////////////////////////////////////////

void LecteurPhraseSimple::seqInst() {
    // <seqInst> ::= <inst> ; { <inst> ; }

    do {
        inst();
        sauterSymCour(";");
    } while ((ls.getSymCour() == "<VARIABLE>") || 
            (ls.getSymCour()=="si") || 
            (ls.getSymCour()=="tantque") || 
            (ls.getSymCour()=="repeter") ||
            (ls.getSymCour()=="lire") ||
            (ls.getSymCour()=="ecrire") );
    // tant que le symbole courant est un debut possible d'instruction...
}

////////////////////////////////////////////////////////////////////////////////

void LecteurPhraseSimple::inst() {
    // <inst> ::= <affectation> | <instSi> | <instTq> | <instRepeter>
   
   if (ls.getSymCour()=="si") {
       instSi();
   }
   else if (ls.getSymCour()=="tantque") {
       instTq();
   }
   else if (ls.getSymCour()=="repeter") {
       instRepeter();
   }       
   else if (ls.getSymCour()=="lire") {
       instLire();
   }   
   else if (ls.getSymCour()=="ecrire") {
       instEcrire();
   }   
   else {
       affectation();
   }
}

////////////////////////////////////////////////////////////////////////////////

void LecteurPhraseSimple::affectation() {
    // <affectation> ::= <variable> = <expression>
    sauterSymCour("<VARIABLE>");
    sauterSymCour("=");
    expression();
}

////////////////////////////////////////////////////////////////////////////////

void LecteurPhraseSimple::expression() {
    // <expression> ::= <terme> { <opAdd> <facteur> }

    terme();
    while (ls.getSymCour() == "+" || ls.getSymCour() == "-") {
        opAdd();
        terme();
    }

}
////////////////////////////////////////////////////////////////////////////////

void LecteurPhraseSimple::terme()
// <terme> ::= <facteur> { <opMult> facteur }
{
    facteur();
    while (ls.getSymCour() == "*" || ls.getSymCour() == "/") {
        ls.suivant();
        facteur();
    }
}
////////////////////////////////////////////////////////////////////////////////

void LecteurPhraseSimple::facteur() {
    // <facteur> ::= <entier>  |  <variable>  |  <opUnaire> <expBool>  |  ( <expBool> )

    if (ls.getSymCour() == "<VARIABLE>" || ls.getSymCour() == "<ENTIER>") {
        ls.suivant();
    }
    else if ((ls.getSymCour() == "-") || (ls.getSymCour() == "non")) {
        ls.suivant();
        expBool();
        
    } else if (ls.getSymCour() == "(") {
        ls.suivant();
        expBool();
        sauterSymCour(")");
        
    } else
        erreur("<facteur>");
}


////////////////////////////////////////////////////////////////////////////////

void LecteurPhraseSimple::testerSymCour(string ch) {
    if (ls.getSymCour() != ch) {
        cout << endl << "-------- Erreur ligne " << ls.getLigne()
                << " - Colonne " << ls.getColonne() << endl << "   Attendu : "
                << ch << endl << "   Trouve  : " << ls.getSymCour() << endl
                << endl;
        exit(0); // plus tard, on levera une exception
    }
}

////////////////////////////////////////////////////////////////////////////////

void LecteurPhraseSimple::sauterSymCour(string ch) {
    testerSymCour(ch);
    ls.suivant();
}

////////////////////////////////////////////////////////////////////////////////

void LecteurPhraseSimple::erreur(string mess) {
    cout << endl << "-------- Erreur ligne " << ls.getLigne() << " - Colonne "
            << ls.getColonne() << endl << "   Attendu : " << mess << endl
            << "   Trouve  : " << ls.getSymCour() << endl << endl;
    exit(0); // plus tard, on levera une exception

}

void LecteurPhraseSimple::opAdd()
// <opAdd> ::= + | -
{
    if (ls.getSymCour() == "+" || ls.getSymCour() == "-")
        ls.suivant();
    else
        erreur("<opAdd>");
}

////////////////////////////////////////////////////////////////////////////////

void LecteurPhraseSimple::opMult()
// <opMult> ::= * | /
{
    if (ls.getSymCour() == "*" || ls.getSymCour() == "/")
        ls.suivant();
    else
        erreur("<opMult>");
}

////////////////////////////////////////////////////////////////////////////////

void LecteurPhraseSimple::expBool() {
    // <expBool> ::= <relation> { <opRel> <relation> }

    relation();
    while (ls.getSymCour() == "et" || ls.getSymCour() == "ou") {
        if (ls.getSymCour() =="et") {                
                    opBool();
                    relation();
                }        
        else {
        opBool();
        relation();
        }
    }
}

////////////////////////////////////////////////////////////////////////////////

void LecteurPhraseSimple::opBool() {
    if (ls.getSymCour() == "et" || ls.getSymCour() == "ou")
        ls.suivant();
    else
        erreur("<opBool>");
}

////////////////////////////////////////////////////////////////////////////////

void LecteurPhraseSimple::relation() {
    // <relation> ::= <expression> { <opRel> <expression> }
    expression();
    while ((ls.getSymCour() == "==") ||
            (ls.getSymCour() == "!=") ||
            (ls.getSymCour() == "<=") ||
            (ls.getSymCour() == ">=") ||
            (ls.getSymCour() == "<") ||
            (ls.getSymCour() == ">")) {

        opRel();
        expression();

    }
}

////////////////////////////////////////////////////////////////////////////////

void LecteurPhraseSimple::opRel() {
    if ((ls.getSymCour() == "==") ||
            (ls.getSymCour() == "!=") ||
            (ls.getSymCour() == "<=") ||
            (ls.getSymCour() == ">=") ||
            (ls.getSymCour() == "<") ||
            (ls.getSymCour() == ">"))
        ls.suivant();
    else
        erreur("<opRel>");
}

////////////////////////////////////////////////////////////////////////////////

void LecteurPhraseSimple::opUnaire() {
    if (ls.getSymCour() == "non" || ls.getSymCour() == "-")
        ls.suivant();
    else
        erreur("<opUnaire>");
}

////////////////////////////////////////////////////////////////////////////////

void LecteurPhraseSimple::instSi() {
    // <instSi> ::= si ( <expBool> ) <seqInst> { sinonsi ( <expBool> ) <seqInst> } [ sinon <seqInst> ] finsi
    sauterSymCour("si");
    sauterSymCour("(");
    expBool();    
    sauterSymCour(")");
    seqInst();
    
        while (ls.getSymCour() == "sinonsi") {
            sauterSymCour("sinonsi");
            sauterSymCour("(");
            expBool();    
            sauterSymCour(")");
            seqInst();
        }
   if (ls.getSymCour() == "sinon") {
   ls.suivant();
   seqInst();
   }
   sauterSymCour("finsi");
}
////////////////////////////////////////////////////////////////////////////////

void LecteurPhraseSimple::instTq() {
    //<instTq> ::= tantque (<expBool>) <seqInst> fintantque
   sauterSymCour("tantque");
   sauterSymCour("(");
   expBool();
   sauterSymCour(")");
   seqInst();
   sauterSymCour("fintantque");
   
}
////////////////////////////////////////////////////////////////////////////////

void LecteurPhraseSimple::instRepeter() {    
    //<instRepeter> ::= repeter <seqInst> jusqua (<expBool>)
    sauterSymCour("repeter");
    seqInst();
    sauterSymCour("jusqua");
    sauterSymCour("(");
    expBool();
    sauterSymCour(")");

//    }
}

void LecteurPhraseSimple::instLire() {    
    //<instLire> ::= lire (<variable>)
    sauterSymCour("lire");
    sauterSymCour("(");
    sauterSymCour("<VARIABLE>");
    sauterSymCour(")");
}
    
 void LecteurPhraseSimple::instEcrire() {    
    //<instEcrire> ::= ecrire (<expression> | <chaine>)
     
     sauterSymCour("ecrire");
    sauterSymCour("(");    
    if (ls.getSymCour()== "<CHAINE>") {
        ls.suivant();
    }
    else {
        expression();
    }
                
    sauterSymCour(")");
 }
    

////////////////////////////////////////////////////////////////////////////////





